home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / pvm34b3.zip / pvm34b3 / pvm3 / pvmgs / pvmgs_core.c < prev    next >
C/C++ Source or Header  |  1997-07-22  |  13KB  |  416 lines

  1.  
  2. static char rcsid[] =
  3.     "$Id: pvmgs_core.c,v 1.4 1997/07/09 13:51:28 pvmsrc Exp $";
  4.  
  5. /*
  6.  *         PVM version 3.4:  Parallel Virtual Machine System
  7.  *               University of Tennessee, Knoxville TN.
  8.  *           Oak Ridge National Laboratory, Oak Ridge TN.
  9.  *                   Emory University, Atlanta GA.
  10.  *      Authors:  J. J. Dongarra, G. E. Fagg, M. Fischer
  11.  *          G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci,
  12.  *         P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam
  13.  *                   (C) 1997 All Rights Reserved
  14.  *
  15.  *                              NOTICE
  16.  *
  17.  * Permission to use, copy, modify, and distribute this software and
  18.  * its documentation for any purpose and without fee is hereby granted
  19.  * provided that the above copyright notice appear in all copies and
  20.  * that both the copyright notice and this permission notice appear in
  21.  * supporting documentation.
  22.  *
  23.  * Neither the Institutions (Emory University, Oak Ridge National
  24.  * Laboratory, and University of Tennessee) nor the Authors make any
  25.  * representations about the suitability of this software for any
  26.  * purpose.  This software is provided ``as is'' without express or
  27.  * implied warranty.
  28.  *
  29.  * PVM version 3 was funded in part by the U.S. Department of Energy,
  30.  * the National Science Foundation and the State of Tennessee.
  31.  */
  32.  
  33. /* This is the core of the group server. Everything is now dynamically
  34.    allocated keep memory cost down and allow larger groups.  */
  35. /*
  36.  *    pvmgs.c
  37.  *    PVM group server
  38.  *
  39.  *    This program maintains group lists.  Processes may join or add
  40.  *    by sending the appropriate request to the group server.
  41.  *    
  42.  *    4 Mar 1993 adamb: Fixed gs_barrier to reset the barrier 
  43.  *        after it's been reached
  44.  *    8 Jul 1993 adamb: Fixed gs_register'pvm_delete so it won't
  45.  *        print bogus error messages
  46.  *    6 Feb 1994 adamb: Added DEADTID functionality, including removing
  47.  *        a taskid from the blocking barrier list if needed
  48.  *     24 Apr 1994 Donato: Added gs_tidlist() in exchange for gs_bcast()
  49.  *      1 May 1994 Papadopoulos: removed length limit for groupnames
  50.  *
  51. */
  52.  
  53.  
  54.  
  55. #include <stdio.h>
  56. #include "pvm3.h"
  57. #include "pvmalloc.h"
  58. #include "pvmgsd.h"
  59.  
  60. /* ================ main() ========================================= */
  61. /* Main program for the group server                                 */
  62. int
  63. main( argc, argv )
  64. int argc;
  65. char *argv[];
  66. {
  67.     GROUP_LIST hash_list[HASHSIZE];    /* open hashing table */
  68.     int ngroups, gstid;
  69.     int nameindex;                     /* index of pvmgs-defnd names */
  70.  
  71.     /* attach to the virtual machine */
  72.     if( (gstid = pvm_mytid()) < 0 ) 
  73.     {
  74.         pvm_perror( GSNAME );
  75.         return( -1 );
  76.     }
  77.  
  78.     /* register this group server */
  79.     if ( !gs_register( GSNAME, gstid ) ) 
  80.     {
  81.         /* initialize the data structures */
  82.         gs_init( hash_list, &ngroups );
  83.  
  84.         /* handle the group server functions */
  85.         gs_handle( hash_list, &ngroups, &gstid );
  86.     }
  87.  
  88.     pvm_exit();
  89.  
  90.     return( PvmOk );
  91. }
  92.  
  93. /* ================ gs_init() ====================================== */
  94. /* Initialize the data structures for holding group data             */
  95. int 
  96. gs_init( hash_list, ngroups )
  97. GROUP_LIST_PTR hash_list; 
  98. int *ngroups;
  99. {
  100.     int i;
  101.     *ngroups = 0;
  102.     gs_hash_init( hash_list );
  103.     return( PvmOk );
  104. }
  105.  
  106. /* ================ gs_deadtid() =================================== */
  107. /* Called when a tid has left the VM ands needs to be deleted from   */
  108. /* all existing groups                                               */
  109. int
  110. gs_deadtid( tid, hash_list, ngroups )
  111. int tid;
  112. GROUP_LIST_PTR hash_list;
  113. int *ngroups;
  114. {
  115.     GROUP_LIST_PTR current;
  116.     GROUP_LIST_PTR next;
  117.     int i;
  118.  
  119.     for ( i=0; i < HASHSIZE ; i++ ) /* go thru entire list of groups */
  120.     {
  121.         current = hash_list+i;
  122.         current = current->next;
  123.         while ( current != (GROUP_LIST_PTR) NULL )
  124.         {
  125.             next = current->next;    /* call to gs_leave may free */
  126.                                     /* struct pointed to by current */
  127.             gs_leave( current->group->name, tid, hash_list, ngroups );
  128.             current = next;
  129.         }
  130.     }
  131.  
  132.     return( PvmOk );
  133. }
  134.  
  135. /* ================ gs_pstate () =================================== */
  136. /* Dump the information held by the group server                     */
  137. int
  138. gs_pstate( name, hash_list, ngroups )
  139. char *name;
  140. GROUP_LIST_PTR hash_list;
  141. int *ngroups;
  142. {
  143.     GROUP_LIST_PTR current;
  144.     GROUP_STRUCT_PTR group;
  145.     int i, j;
  146.  
  147.     fprintf( stderr, "%s 0x%x, %d groups:\n",
  148.             name, pvm_mytid(), *ngroups);
  149.  
  150.     for ( i=0 ; i < HASHSIZE ; i++ ) /* go thru entire list of groups */
  151.     {
  152.         current = hash_list + i;
  153.         current = current->next;
  154.         while ( current != (GROUP_LIST_PTR) NULL )
  155.         {
  156.             group = current->group;
  157.             fprintf( stderr, "group: %s  size: %d ", 
  158.                     group->name, group->ntids );
  159.             fprintf( stderr, "barrier_count: %d barrier_reached %d\n ", 
  160.                     group->barrier_count, group->barrier_reached );
  161.             fprintf( stderr, "sgroup_count: %d sgroup_reached %d\n ", 
  162.                     group->sgroup_count, group->sgroup_reached );
  163.             fprintf( stderr, " Tids: \n" );
  164.             for ( j=0 ; j < group->maxntids ; j++ )
  165.                 if ( group->tids[j] != NOTID )
  166.                     fprintf( stderr, "(%d,  0x%x) ",
  167.                             j, group->tids[j] );
  168.             fprintf( stderr, "\n" );
  169.             if ( group->barrier_reached > 0 )
  170.             {
  171.                 fprintf( stderr, "tids waiting on barrier:\n" );
  172.                 for ( j=0 ; j < group->barrier_reached ; j++ )
  173.                     fprintf( stderr, "0x%x  ", group->btids[j] );
  174.                 fprintf( stderr, "\n"    );
  175.             }
  176.             if ( group->sgroup_reached > 0 )
  177.             {
  178.                 fprintf( stderr,
  179.                         "tids waiting on static formation:\n" );
  180.                 if ( group->stids != (int *) NULL )
  181.                     for ( j=0 ; j < group->sgroup_reached ; j++ )
  182.                         fprintf( stderr, "0x%x  ", group->stids[j] );
  183.                 fprintf( stderr, "\n" );
  184.             }
  185.             if ( group->nhosts > 0 )
  186.             {
  187.                 fprintf( stderr, "Host characterization:\n" );
  188.                 for ( j=0 ; j < group->nhosts ; j++ )
  189.                     fprintf( stderr, "host %x - %d procs, %x coord \n",
  190.                             pvm_tidtohost( group->pcoord[j] ), 
  191.                             group->np_onhost[j], group->pcoord[j] ); 
  192.             }
  193.             current = current->next;
  194.         }
  195.     }
  196.  
  197.     return( PvmOk );
  198. }
  199.  
  200. /* ================ gs_ls () ======================================= */
  201. /* Pack up a message that lists the information held by the group    */
  202. /* server                                                            */
  203. int
  204. gs_ls( hash_list, ngroups )
  205. GROUP_LIST_PTR hash_list;
  206. int *ngroups;
  207. {
  208.     GROUP_LIST_PTR current;
  209.     GROUP_LIST_PTR next;
  210.     GROUP_STRUCT_PTR group;
  211.     int i, j;
  212.  
  213.     pvm_initsend( PvmDataDefault );
  214.     pvm_pkint( ngroups, 1, 1 );
  215.     for ( i=0 ; i < HASHSIZE ; i++ ) /* go thru entire list of groups */
  216.     {
  217.         current = hash_list + i;
  218.         current = current->next;
  219.         while ( current != (GROUP_LIST_PTR) NULL )
  220.         {
  221.             group = current->group;
  222.             pvm_pkint( &(group->len), 1, 1 );
  223.             pvm_pkstr( group->name );
  224.             pvm_pkint( &(group->ntids), 1, 1 );
  225.             pvm_pkint( &(group->maxntids), 1, 1 );
  226.             pvm_pkint( &(group->barrier_count), 1, 1 );
  227.             pvm_pkint( &(group->barrier_reached), 1, 1 );
  228.             pvm_pkint( group->tids,group->maxntids, 1 );
  229.             if ( group->barrier_reached > 0 )
  230.                 pvm_pkint( group->btids, group->barrier_reached, 1 ); 
  231.             current = current->next;
  232.         }
  233.     }
  234.  
  235.     return( PvmOk );
  236. }
  237.  
  238. /* ================ gs_handle () =================================== */
  239. /* Handle the incoming msg tags and call the appropriate operation   */
  240. int
  241. gs_handle( hash_list, ngroups, gstid )
  242. GROUP_LIST_PTR hash_list;
  243. int *ngroups, *gstid;
  244. {
  245.     int len, msgtag, tid, gid, cc, ftid, inst, i, size, ntids, listsize;
  246.     int cnt, hosttid, nhosts, nmem_onhost, pcoord;
  247.     int *nmem_onhostv = (int *) NULL, *pcoordv = (int *) NULL; 
  248.     int mxupklen = 0;
  249.     GROUP_STRUCT_PTR group;
  250.     char *groupname = (char *) NULL;
  251.     int *tidlist = (int *) NULL;
  252.     int maxntids = 0, info;
  253.     int gstate;
  254.  
  255.     while ( 1 )  
  256.     {
  257.         if ( (cc = pvm_recv( -1, -1 )) < 0 )  /* receive a request */ 
  258.         {
  259.             pvm_perror( "gs_handle(recv)" );
  260.             return( cc );
  261.         }
  262.         /* get: length of message, message tag, and sending tid */
  263.         if ( (cc = pvm_bufinfo( pvm_getrbuf(), &len, &msgtag, &tid ))
  264.                 < 0 ) 
  265.         {
  266.             pvm_perror("gs_handle(bufinfo)");
  267.             return( cc );
  268.         }
  269.  
  270.         /* Most group functions require unpacking a group name, so */
  271.         /* Make sure variable groupname is always long enough */
  272.         REALLOCSTRING( len, mxupklen , groupname, "gs_handle(entry)" );
  273.  
  274.         switch( msgtag ) 
  275.         {
  276.             case (DIE):        /* leave a suicide note */
  277.                 gs_pstate( "pvmgs", hash_list, ngroups );
  278.                 return( PvmOk );
  279.  
  280.             case (JOIN):    /* join a group with the lowest avail gid */
  281.                 pvm_upkstr( groupname );
  282.                 gid = gs_join( groupname, tid, hash_list, ngroups );
  283.                 /* tell me if the tid dies */
  284.                 if ( pvm_notify( PvmTaskExit, DEADTID, 1, &tid ) < 0 ) 
  285.                     pvm_perror( "pvmgs-join" );
  286.                 SENDINTRESULT( gid, tid, msgtag, "gs_handle(join)" );
  287.                 break;
  288.  
  289.             case (LEAVE):    /* leave a group */
  290.                 pvm_upkstr( groupname );
  291.                 cc = gs_leave( groupname, tid, hash_list, ngroups );
  292.                 SENDINTRESULT( cc, tid, msgtag, "gs_handle(leave)" );
  293.                 break;
  294.  
  295.             case (DEADTID):    /* task in one or more groups has died */ 
  296.                 pvm_upkint( &tid, 1, 1 );
  297.                 if ( tid < 0 ) 
  298.                 {
  299.                     fprintf( stderr, "pvmgs: weird dead tid x%x %d\n",
  300.                             tid, tid );
  301.                     break;
  302.                 }
  303.                 cc = gs_deadtid( tid, hash_list, ngroups );
  304.                 break;
  305.  
  306.             case (BARRIER):    /* Handle barrier for a group */ 
  307.             case (BARRIERV):
  308.                 pvm_upkstr( groupname );
  309.                 pvm_upkint( &cnt, 1, 1 );
  310.                 cc = gs_barrier( groupname, msgtag,
  311.                         cnt, tid, hash_list, ngroups );
  312.                 /* send back a response only if there is an error */
  313.                 if ( cc < 0 ) 
  314.                     SENDINTRESULT( cc, tid, msgtag,
  315.                             "gs_handle(barrier)" );
  316.                 break;
  317.  
  318.             case (BCAST):    /* broadcast and tidlists */
  319.             case (TIDLIST): 
  320.                 pvm_upkstr( groupname );
  321.                 cc = gs_tidlist( groupname, ((msgtag == BCAST) ? 0 : 1),
  322.                         hash_list, ngroups, &gstate ); 
  323.                 if ( cc )  /* there was error, send back error code */
  324.                     SENDINTRESULT( cc, tid, msgtag, "gs_handle(bcast)" )
  325.                 else  /* send the already-packed tid-list */
  326.                 {
  327.                     PK_STATE( tid, gstate, groupname, hash_list,
  328.                             ngroups, "gs_handle(bcast)" );
  329.                     SENDRESULT( tid, msgtag, "gs_handle(bcast)" );
  330.                 }
  331.                 break;
  332.  
  333.             case (GSIZE):    /* return the current group size */
  334.                 pvm_upkstr( groupname );
  335.                 size = gs_gsize( groupname, hash_list, ngroups,
  336.                         &gstate );
  337.                 PK_IRESULT( size, "gs_handle(gsize)" );
  338.                 PK_STATE( tid, gstate, groupname, hash_list, ngroups,
  339.                         "gs_handle(gsize)" );
  340.                 SENDRESULT( tid, msgtag, "gs_handle(gsize)" );
  341.                 break;
  342.  
  343.             case (GETINST):    /* return inst of tid in group groupname */
  344.                 pvm_upkstr( groupname );
  345.                 pvm_upkint( &ftid, 1, 1 );
  346.                 inst = gs_getinst( groupname, ftid, hash_list, ngroups,
  347.                         &gstate );
  348.                 PK_IRESULT( inst, "gs_handle(getinst)" );
  349.                 PK_STATE( tid, gstate, groupname, hash_list, ngroups,
  350.                         "gs_handle(getinst)" );
  351.                 SENDRESULT( tid, msgtag, "gs_handle(getinst)" );
  352.                 break;
  353.  
  354.             case (GETTID):    /* return tid from (group,instance) pair */
  355.                 pvm_upkstr( groupname );
  356.                 pvm_upkint( &inst, 1, 1 );
  357.                 ftid = gs_gettid( groupname, inst, hash_list, ngroups,
  358.                         &gstate );
  359.                 PK_IRESULT( ftid, "gs_handle(gettid)" );
  360.                 PK_STATE( tid, gstate, groupname, hash_list, ngroups,
  361.                         "gs_handle(gettid)" );
  362.                 SENDRESULT( tid, msgtag, "gs_handle(gettid)" );
  363.                 break;
  364.  
  365.             case (STATICGROUP):    /* Form a static group */
  366.                 pvm_upkstr( groupname );
  367.                 pvm_upkint( &size, 1, 1 );
  368.                 info = gs_static( groupname, size, tid, hash_list,
  369.                         ngroups );
  370.                 if ( info < 0 )
  371.                     SENDINTRESULT( info, tid, msgtag,
  372.                             "gs_handle(static)" );
  373.                 /* gs_static will mcast list to group when formed */
  374.                 break;
  375.  
  376.             case DUMP:
  377.                 gs_pstate( "DUMP", hash_list, ngroups );
  378.                 break;
  379.  
  380.             case GSLS: 
  381.                 gs_ls( hash_list, ngroups );
  382.                 pvm_send( tid, msgtag );
  383.                 break;
  384.  
  385.             case HOSTCHAR:    /* get host characteristics */
  386.                 pvm_upkstr( groupname );
  387.                 pvm_upkint( &hosttid, 1, 1 );
  388.                 gs_host_char( groupname, hash_list, ngroups, hosttid, 
  389.                         &pcoord, &nmem_onhost, &nhosts, &gstate );
  390.                 PK_IRESULT( nhosts, "gs_handle(hostchar)" );
  391.                 pvm_pkint( &nmem_onhost, 1, 1 );
  392.                 pvm_pkint( &pcoord, 1, 1 ); 
  393.                 PK_STATE( tid, gstate, groupname, hash_list, ngroups,
  394.                         "gs_handle(hostchar)" );
  395.                 SENDRESULT( tid, msgtag, "gs_handle(hostchar)" );
  396.                 break; 
  397.  
  398.             case HOSTCHARV:    /* get host characteristics */
  399.                 pvm_upkstr( groupname );
  400.                 gs_host_all( groupname, hash_list, ngroups, &pcoordv, 
  401.                         &nmem_onhostv, &nhosts, &gstate );
  402.                 PK_IRESULT( nhosts, "gs_handle(hostchar)" );
  403.                 pvm_pkint( nmem_onhostv, nhosts, 1 );
  404.                 pvm_pkint( pcoordv, nhosts, 1 ); 
  405.                 PK_STATE( tid, gstate, groupname, hash_list, ngroups,
  406.                         "gs_handle(hostchar)" );
  407.                 SENDRESULT( tid, msgtag, "gs_handle(hostchar)" );
  408.                 break;
  409.  
  410.             default:
  411.                 break;
  412.         }  /* Switch - statement */
  413.     } /* While - statement */
  414.  
  415.